package v2ray

import (
	"gitee.com/yysf-xin/dproxy/pkg/app"
	"gitee.com/yysf-xin/dproxy/pkg/tools"
	core "github.com/v2fly/v2ray-core/v5"
	"github.com/v2fly/v2ray-core/v5/app/dispatcher"
	"github.com/v2fly/v2ray-core/v5/app/dns"
	_ "github.com/v2fly/v2ray-core/v5/app/dns"
	"github.com/v2fly/v2ray-core/v5/app/log"
	"github.com/v2fly/v2ray-core/v5/app/policy"
	"github.com/v2fly/v2ray-core/v5/app/proxyman"
	"github.com/v2fly/v2ray-core/v5/app/router"
	clog "github.com/v2fly/v2ray-core/v5/common/log"
	"github.com/v2fly/v2ray-core/v5/common/net"
	"github.com/v2fly/v2ray-core/v5/common/serial"
	"github.com/v2fly/v2ray-core/v5/proxy/freedom"
	_ "github.com/v2fly/v2ray-core/v5/proxy/freedom"
	"github.com/v2fly/v2ray-core/v5/proxy/http"
	"google.golang.org/protobuf/types/known/anypb"
)

type Server struct {
	cfg *core.Config
	ins *core.Instance
}

func NewServer(config *app.Config) (*Server,error) {
	dest,err := net.ParseDestination(":8881")
	if err != nil {
		return nil, err
	}
	fxIp := [][]byte{{183,3,216,237}}
	cfg := &core.Config{
		App: []*anypb.Any{
			serial.ToTypedMessage(&dispatcher.Config{}),
			serial.ToTypedMessage(&proxyman.OutboundConfig{}),
			serial.ToTypedMessage(&proxyman.InboundConfig{}),
			serial.ToTypedMessage(&policy.Config{}),
			serial.ToTypedMessage(&log.Config{
				Error: &log.LogSpecification{
					Type:  log.LogType_Console,
					Level: clog.Severity_Warning,
				},
				Access: &log.LogSpecification{
					Type:  log.LogType_Console,
					Level: clog.Severity_Error,
				},
			}),
			serial.ToTypedMessage(&dns.Config{
				StaticHosts: []*dns.HostMapping{
					{
						Type:   dns.DomainMatchingType_Full,
						Domain: "dns.alidns.com",
						Ip:     [][]byte{{223, 6, 6, 6}},
					},
					{
						Type:   dns.DomainMatchingType_Full,
						Domain: "fx-sit.inn.sf-express.com",
						Ip:     fxIp,
					},
					{
						Type:   dns.DomainMatchingType_Full,
						Domain: "fx-dev.inn.sf-express.com",
						Ip:     fxIp,
					},
				},
				NameServer: []*dns.NameServer{
					{
						Address: &net.Endpoint{
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Domain{
									Domain: "https://dns.alidns.com/dns-query",
								},
							},
							Network: net.Network_TCP,
						},
					},
					{
						Address: &net.Endpoint{
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Domain{
									Domain: "localhost",
								},
							},
						},
					},
				},
				DisableCache: false,
			}),
			serial.ToTypedMessage(&router.Config{
				DomainStrategy: router.DomainStrategy_IpIfNonMatch,
				Rule: []*router.RoutingRule{
				},
			}),
		},
		Inbound: []*core.InboundHandlerConfig {
			{
				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
					PortRange: net.SinglePortRange(dest.Port),
					Listen:    net.NewIPOrDomain(dest.Address),
				}),
				ProxySettings: serial.ToTypedMessage(&http.ServerConfig{
				}),
			},
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&freedom.Config{
					DomainStrategy: freedom.Config_USE_IP,
				}),
			},
		},
	}
	ins,err := core.New(cfg)

	if err != nil {
		return nil, err
	}

	return &Server{
		cfg: cfg,
		ins: ins,
	},nil
}

func (s *Server) Start() (err error) {
	if s.ins == nil {
		s.ins,err = core.New(s.cfg)
		if err != nil {
			return err
		}
	}
	err = s.ins.Start()
	return err
}

func (s *Server) Stop() {
	if s.ins != nil {
		err := s.ins.Close()
		if err != nil {
			tools.Log.Println("close v2ray err",err)
		}
	}
}

